<template>
    <a-form
        ref="formRef"
        :model="internalModel"
        :rules="computedRules"
        v-bind="$attrs"
        @finish="handleFinish"
        @finishFailed="handleFinishFailed"
    >
        <a-row :gutter="16">
            <a-col v-for="item in formItems" :key="item.name">
                <a-form-item :label="item.label" :name="item.name" :rules="item.rules">
                    <!-- Input -->
                    <a-input
                        v-if="item.type === 'input'"
                        v-model:value="internalModel[item.name]"
                        v-bind="item.componentProps"
                    />
                    <!-- InputNumber -->
                    <a-input-number
                        v-else-if="item.type === 'input-number'"
                        v-model:value="internalModel[item.name]"
                        v-bind="item.componentProps"
                        style="width: 100%"
                    />
                    <!-- Password -->
                    <a-input-password
                        v-else-if="item.type === 'input-password'"
                        v-model:value="internalModel[item.name]"
                        v-bind="item.componentProps"
                    />
                    <!-- TextArea -->
                    <a-textarea
                        v-else-if="item.type === 'textarea'"
                        v-model:value="internalModel[item.name]"
                        v-bind="item.componentProps"
                    />
                    <!-- Select -->
                    <a-select
                        v-else-if="item.type === 'select'"
                        v-model:value="internalModel[item.name]"
                        v-bind="omit(item.componentProps!, ['options'])"
                        :options="item.componentProps?.options"
                        show-search
                        style="width: 100%"
                    />
                    <!-- DatePicker -->
                    <a-date-picker
                        v-else-if="item.type === 'date-picker'"
                        v-model:value="internalModel[item.name]"
                        v-bind="item.componentProps"
                        style="width: 100%"
                    />
                    <!-- RangePicker -->
                    <a-range-picker
                        v-else-if="item.type === 'date-range-picker'"
                        v-model:value="internalModel[item.name]"
                        v-bind="item.componentProps"
                        style="width: 100%"
                    />
                    <!-- CheckboxGroup -->
                    <a-checkbox-group
                        v-else-if="item.type === 'checkbox'"
                        v-model:value="internalModel[item.name]"
                        :options="item.componentProps?.options"
                    />
                    <!-- RadioGroup -->
                    <a-radio-group
                        v-else-if="item.type === 'radio'"
                        v-model:value="internalModel[item.name]"
                        :options="item.componentProps?.options"
                    />
                </a-form-item>
            </a-col>
        </a-row>
    </a-form>
</template>

<script setup lang="ts">
// import { omit } from "lodash-es";
import type { Dayjs } from "dayjs";
import { reactive, ref, watch } from "vue";

import type { FormItemConfig } from "../types/form-config";

const props = withDefaults(
    defineProps<{
        formItems: FormItemConfig[];
        initialValues?: Record<string, any>; // 表单数据模型对象（同时设置了初始值）。属性必须和 formItems 中定义的 name 一致
    }>(),
    {
        formItems: () => [
            {
                name: "username",
                label: "用户名",
                type: "input",
                rules: [{ required: true, message: "请输入用户名", whitespace: true }],
                componentProps: { placeholder: "请输入用户名" }
            },
            {
                name: "age",
                label: "年龄",
                type: "input-number",
                rules: [{ required: true, message: "请输入年龄", whitespace: true }],
                componentProps: { placeholder: "请输入年龄" }
            },
            {
                type: "select",
                name: "gender",
                label: "性别",
                componentProps: {
                    placeholder: "请选择性别",
                    options: [
                        {
                            label: "男",
                            value: "male"
                        },
                        {
                            label: "女",
                            value: "female"
                        },
                        {
                            label: "未知",
                            value: "unknown"
                        }
                    ]
                }
            },
            {
                type: "date-range-picker",
                name: "dateRange",
                label: "日期范围"
            }
        ],
        initialValues: () =>
            ({
                username: "",
                gender: void 0, // 下拉框属性的初始值应为 undefined，否则无法显示 placeholder 值
                age: void 0, // 数字输入框的初始值也可设为 undefined，避免 0 的默认值
                dateRange: null as [Dayjs, Dayjs] | null // 日期范围选择框的初始值也为 null，避免默认的今天，有效值为 Dayjs 实例数组
            }) as any
    }
);

const emit = defineEmits<{
    (e: "finish", values: Record<string, any>): void;
    (e: "finishFailed", errorInfo: any): void;
    (e: "update:modelValue", values: Record<string, any>): void;
}>();

function omit(obj: Record<string, any>, keys: string[]) {
    if (!obj) return {};
    const res = { ...obj };
    keys.forEach(k => delete res[k]);
    return res;
}

const computedRules = computed(() => {
    const rules: Record<string, any> = {};
    props.formItems.forEach(item => {
        rules[item.name] = item.rules;
    });
    return rules;
});

// 表单引用
const formRef = ref();

// 构建初始 model
const buildInitialModel = () => {
    const model: Record<string, any> = {};
    props.formItems.forEach(item => {
        model[item.name] = undefined;
    });
    return model;
};

// 内部 model
const internalModel = reactive<Record<string, any>>({ ...buildInitialModel() });

// 监听 initialValues 变化（用于编辑回显）
watch(
    () => props.initialValues,
    newVal => {
        if (newVal && Object.keys(newVal).length > 0) {
            // 回显数据
            Object.assign(internalModel, buildInitialModel(), newVal);
        } else {
            // 清空
            Object.assign(internalModel, buildInitialModel());
            formRef.value?.clearValidate(); // 重置表单验证状态
        }
    },
    { immediate: true }
);

// 触发 submit
const handleFinish = (values: Record<string, any>) => {
    emit("finish", values);
};

const handleFinishFailed = (errorInfo: any) => {
    emit("finishFailed", errorInfo);
};

// 暴露方法给父组件（如手动校验、清空等）
defineExpose({
    formRef,
    resetFields: () => formRef.value?.resetFields(),
    validateFields: (...args: any[]) => formRef.value?.validateFields(...args),
    getFieldsValue: () => ({ ...internalModel })
});
</script>
